package com.rex.saas.mqtt;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rex.saas.bean.DeviceBasicData;
import com.rex.saas.bean.ResultCode;
import com.rex.saas.constants.ApiConstant;
import com.rex.saas.constants.Constants;
import com.rex.saas.service.RexolarApiClient;
import com.rex.saas.utils.MacAddressUtil;
import com.rex.saas.utils.Sm2CryptoUtil;
import com.rex.saas.utils.Sm4CryptoUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * MQTT回调函数
 *
 * @author wt
 */
@Slf4j
@Component
public class ListenerCallback implements MqttCallback {


    @Autowired
    private MqttConnect mqttConnect;

    @Autowired
    private RexolarApiClient rexolarApiClient;

    /**
     * MQTT 断开连接会执行此方法
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("connectionLost 断开了MQTT连接 clientId:{}, ：{}", mqttConnect.getMqttClient().getClientId(), throwable.getMessage());
        log.error(throwable.getMessage(), throwable);
        while (!mqttConnect.getMqttClient().isConnected()){
            log.info("connectionLost 正在尝试重新连接MQTT");
            mqttConnect.reConnect("/iot/"+ MacAddressUtil.getMacAddress()+"/down");
            log.info("connectionLost reConnect MQTT连接成功, clientId：{} ", mqttConnect.getMqttClient().getClientId());
        }
    }

    /**
     * publish发布成功后会执行到这里
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.info("deliveryComplete 发布成功");
    }

    /**
     * subscribe订阅后得到的消息会执行到这里
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("messageArrived " + topic + " message：{}", new String(message.getPayload()));
        String msg = new String(message.getPayload());
        if(StringUtils.isEmpty(msg)){
            log.error("ListenerCallback messageArrived msg is empty");
            return;
        }
        String msgStr = Sm4CryptoUtil.decrypt(msg);
        log.info("ListenerCallback messageArrived decrypt msg：{}", msgStr);
        JSONObject jsonObject = JSONObject.parseObject(msgStr);
        if(jsonObject==null){
            log.error("ListenerCallback messageArrived jsonObject is empty");
            return;
        }
        try {
            JSONObject ackResponse = doBusiness(msg);
            assert ackResponse != null;
            String ackResponseStr =  Sm4CryptoUtil.encrypt(ackResponse.toJSONString());
            mqttConnect.pub("/paas/"+MacAddressUtil.getMacAddress()+"/up", ackResponseStr);
        } catch (MqttException e) {
            log.error("ListenerCallback messageArrived MqttException, msg:{}", msg,  e);
        }
    }

    private JSONObject doBusiness(String msg) throws MqttException {
        JSONObject ackResponse = new JSONObject();
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String functionCode = jsonObject.getString("FunctionCode");
        if (StringUtils.isEmpty(functionCode)){
            log.error("MaListenerCallback messageArrived FunctionCode is empty, msg:{}", msg);
            return null;
        }
        ackResponse.put("FunctionCode", "Ack");
        String seq = jsonObject.getString("Seq");
        if (StringUtils.isEmpty(seq)){
            log.error("MaListenerCallback messageArrived Seq is empty, msg:{}", msg);
            return null;
        }
        String token = rexolarApiClient.getTenantTokenByUser("tenant@rexolar.com", "Rexolar_!@");
        if(StringUtils.isEmpty( token)){
            log.error("MaListenerCallback messageArrived getTenantTokenByUser is empty");
            return null;
        }
        ackResponse.put("FunctionCode", "Ack");
        ackResponse.put("Seq", jsonObject.getString("Seq"));
        String gateWayId = jsonObject.getString("GateWayId");
        JSONObject newPayload = new JSONObject();
        newPayload.put("Code", 0);
        ackResponse.put("Payload", newPayload);
        if (StringUtils.isEmpty(gateWayId)){
            log.error("MaListenerCallback messageArrived GateWayId is empty, msg:{}", msg);
            newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
            newPayload.put("msg", "GateWayId is empty");
            return ackResponse;
        }
        DeviceBasicData gateway = rexolarApiClient.getDeviceByDeviceName(gateWayId, token);
        if (gateway==null){
            log.error("MaListenerCallback messageArrived gateway is null, msg:{}", msg);
            newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
            newPayload.put("msg", "gateway is null");
            return ackResponse;
        }
        long time = System.currentTimeMillis();
        jsonObject.put("DeviceId", gateWayId);
        if ("ReadDevTelemetry".equals(functionCode)){
            String deviceName = jsonObject.getString("DeviceName");
            if (StringUtils.isEmpty(deviceName)){
                log.error("MaListenerCallback ReadDevTelemetry DeviceName is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceName is empty");
                return ackResponse;
            }
            JSONObject payload = jsonObject.getJSONObject("Payload");
            if (payload.isEmpty()){
                log.error("MaListenerCallback ReadDevTelemetry Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if (device==null){
                log.error("MaListenerCallback ReadDevTelemetry device is null, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "device is null");
                return ackResponse;
            }
            Long startTime = payload.getLong("startTime");
            Long endTime = payload.getLong("endTime");
            log.info("MaListenerCallback ReadDevTelemetry startTime:{}, endTime:{}", startTime, endTime);
            if (startTime== null){
                startTime = DateUtil.parse(DateUtil.today(), "yyyy-MM-dd").getTime();
            }
            if (endTime == null) {
                endTime = System.currentTimeMillis();
            }
            if (startTime > endTime){
                log.error("MaListenerCallback ReadDevTelemetry StartTime must less than EndTime, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "StartTime must less than EndTime");
                return ackResponse;
            }
            if (endTime - startTime > 86400000){
                log.error("MaListenerCallback ReadDevTelemetry Time range must less than 24 hours, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Time range must less than 24 hours");
                return ackResponse;
            }
            JSONArray keys = payload.getJSONArray("properties");
            if (keys==null || keys.isEmpty()){
                log.error("MaListenerCallback ReadDevTelemetry keys is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "keys is empty");
                return ackResponse;
            }
            if (keys.size() > 10){
                log.error("MaListenerCallback ReadDevTelemetry keys size must less than 10, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "keys size must less than 10");
                return ackResponse;
            }
            String[] keysArray = new String[keys.size()];
            for (int i = 0; i < keys.size(); i++) {
                keysArray[i] = keys.getString(i);
            }
            JSONObject payLoad = new JSONObject();
            Map<String, Object> timeSeries = rexolarApiClient.getDeviceTimeSeries(device.getCoreId(),
                    token, keysArray, startTime, endTime,
                    100000, false, null, null, false);
            log.info("down getDeviceTimeSeries timeSeries:{}", timeSeries);
            if(CollectionUtils.isEmpty(timeSeries)){
                log.error("down getDeviceTimeSeries error, deviceName:{}, keysArray:{}, startTime:{}, endTime:{}",
                        deviceName, keysArray, startTime, endTime);
                for (String key : timeSeries.keySet()){
                    payLoad.put(key, null);
                }
            }else {
                for (String key : timeSeries.keySet()){
                    List<Map> tmp = (List<Map>) timeSeries.get(key);
                    payLoad.put(key, tmp);
                }
            }
            log.info("getDeviceTimeSeries payLoad:{}", payLoad);
            ackResponse.put("VendorCode", "Rexense");
            ackResponse.put("Timestamp", System.currentTimeMillis());
            ackResponse.put("Seq", seq);
            ackResponse.put("GateWayId", gateWayId);
            ackResponse.put("DeviceName", deviceName);
            ackResponse.put("FunctionCode", "ReadDevTelemetryResponse");
            ackResponse.put("Payload", payLoad);

        }else if ("WriteDevPropertyList".equals(functionCode)){
            String deviceName = jsonObject.getString("DeviceName");
            if (StringUtils.isEmpty(deviceName)){
                log.error("MaListenerCallback DevWriteProperty DeviceName is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceName is empty");
                return ackResponse;
            }
            DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if (device==null){
                log.error("MaListenerCallback DevWriteProperty device is null, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "device is null");
                return ackResponse;
            }
            JSONObject payload = jsonObject.getJSONObject("Payload");
            if (payload.isEmpty()){
                log.error("MaListenerCallback DevWriteProperty Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            if (payload.size() > 10){
                log.error("MaListenerCallback DevWriteProperty keys size must less than 10, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "keys size must less than 10");
                return ackResponse;
            }
            JSONObject gwRpcRequest = new JSONObject();
            gwRpcRequest.put(Constants.Version, "1.0");
            gwRpcRequest.put("VendorCode", "Rexense");
            gwRpcRequest.put("Timestamp", time);
            gwRpcRequest.put("DeviceId", gateway.getName());
            gwRpcRequest.put("Seq", seq);
            gwRpcRequest.put("FunctionCode", "WriteDevPropertyList");
            JSONObject newPayload1 = new JSONObject();
            newPayload1.put("GroupId", "0");
            newPayload1.put("DeviceId", device.getName());
            newPayload1.put("WriteList", payload);
            gwRpcRequest.put("Payload", newPayload1);
            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, gwRpcRequest.toJSONString(), token);
            if (!flag){
                log.error("MaListenerCallback DevWriteProperty updateDeviceAttributes error, gwRpcRequest:{}", gwRpcRequest);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback DevWriteProperty updateDeviceAttributes success, gwRpcRequest:{}", gwRpcRequest);
            }
        }else if ("UpgradeGwApp".equals(functionCode)){
            JSONObject gwRpcRequest = jsonObject.getJSONObject("Payload");
            if (gwRpcRequest==null
                    || StringUtils.isEmpty(gwRpcRequest.getString("URL"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("MD5"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("Size"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("Version"))
            ){
                log.error("MaListenerCallback UpgradeGwApp Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, jsonObject.toJSONString(), token);
            if (!flag){
                log.error("MaListenerCallback UpgradeGwApp updateDeviceAttributes error, jsonObject:{}", jsonObject);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback UpgradeGwApp updateDeviceAttributes success, jsonObject:{}", jsonObject);
            }
        }else if ("PermitAllJoin".equals(functionCode)){
            jsonObject.remove("GateWayId");
            jsonObject.put("DeviceId", gateWayId);
            JSONObject gwRpcRequest = jsonObject.getJSONObject("Payload");
            if (gwRpcRequest==null
                    || StringUtils.isEmpty(gwRpcRequest.get("Duration"))
            ){
                log.error("MaListenerCallback PermitAllJoin Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, jsonObject.toJSONString(), token);
            if (!flag){
                log.error("MaListenerCallback PermitAllJoin updateDeviceAttributes error, jsonObject:{}", jsonObject);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback PermitAllJoin updateDeviceAttributes success, jsonObject:{}", jsonObject);
            }
        }else if ("GetDevList".equals(functionCode)){
            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, jsonObject.toJSONString(), token);
            if (!flag){
                log.error("MaListenerCallback GetDevList updateDeviceAttributes error, jsonObject:{}", jsonObject);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback GetDevList updateDeviceAttributes success, jsonObject:{}", jsonObject);
            }
        }else if ("OTAUpgradeDev".equals(functionCode)){
            JSONObject gwRpcRequest = jsonObject.getJSONObject("Payload");
            if (gwRpcRequest==null
                    || StringUtils.isEmpty(gwRpcRequest.getString("Operate"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("DeviceIds"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("URL"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("MD5"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("Size"))
                    || StringUtils.isEmpty(gwRpcRequest.getString("Version"))
            ){
                log.error("MaListenerCallback OTAUpgradeDev Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, jsonObject.toJSONString(), token);
            if (!flag){
                log.error("MaListenerCallback OTAUpgradeDev updateDeviceAttributes error, jsonObject:{}", jsonObject);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback OTAUpgradeDev updateDeviceAttributes success, jsonObject:{}", jsonObject);
            }
        }else if ("BatchWriteDevPropertyList".equals(functionCode)){
            JSONObject payload = jsonObject.getJSONObject("Payload");
            if (payload.isEmpty()){
                log.error("MaListenerCallback BatchWriteDevPropertyList WriteList is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "WriteList is empty");
                return ackResponse;
            }
            if (payload.size()>10){
                log.error("MaListenerCallback BatchWriteDevPropertyList WriteList size > 10, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "WriteList size > 10");
                return ackResponse;
            }
            JSONArray deviceNames = jsonObject.getJSONArray("DeviceName");
            if(deviceNames.isEmpty()){
                log.error("MaListenerCallback BatchWriteDevPropertyList DeviceNames is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceNames is empty");
                return ackResponse;
            }
            if(deviceNames.size()>20){
                log.error("MaListenerCallback BatchWriteDevPropertyList DeviceNames size > 20, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceNames size > 20");
                return ackResponse;
            }
            for (int i = 0; i < deviceNames.size(); i++) {
                String deviceName = deviceNames.getString(i);
                DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
                if (device==null){
                    log.error("MaListenerCallback BatchWriteDevPropertyList device is empty, deviceName:{}", deviceName);
                    continue;
                }
                JSONObject gwRpcRequest = new JSONObject();
                gwRpcRequest.put(Constants.Version, "1.0");
                gwRpcRequest.put("VendorCode", "Rexense");
                gwRpcRequest.put("Timestamp", time);
                gwRpcRequest.put("DeviceId", gateway.getName());
                gwRpcRequest.put("Seq", seq);
                gwRpcRequest.put("FunctionCode", "WriteDevPropertyList");
                JSONObject newPayload1 = new JSONObject();
                newPayload1.put("GroupId", "0");
                newPayload1.put("DeviceId", device.getName());
                newPayload1.put("WriteList", payload);
                gwRpcRequest.put("Payload", newPayload1);
                boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE, gwRpcRequest.toJSONString(), token);
                if (!flag){
                    log.error("MaListenerCallback BatchWriteDevPropertyList updateDeviceAttributes error, gwRpcRequest:{}", gwRpcRequest);
                    newPayload.put("msg", "updateDeviceAttributes error");
                    newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                }else {
                    log.info("MaListenerCallback BatchWriteDevPropertyList updateDeviceAttributes success, jsonObject:{}", jsonObject);
                }
            }
        }else if ("ReadDevPropertyList".equals(functionCode)){
            JSONObject payload = jsonObject.getJSONObject("Payload");
            if (payload.isEmpty()){
                log.error("MaListenerCallback  WriteList is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "WriteList is empty");
                return ackResponse;
            }
            String deviceName = payload.getString("DeviceId");
            if (StringUtils.isEmpty(deviceName)){
                log.error("MaListenerCallback ReadDevPropertyList DeviceId is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceId is empty");
                return ackResponse;
            }
            JSONArray propertyList = payload.getJSONArray("ReadList");
            if (propertyList.isEmpty()){
                log.error("MaListenerCallback ReadDevPropertyList ReadList is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "ReadList is empty");
                return ackResponse;
            }
            if (propertyList.size()>10){
                log.error("MaListenerCallback ReadDevPropertyList ReadList size > 10, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "ReadList size > 10");
                return ackResponse;
            }
            DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if (device==null){
                log.error("MaListenerCallback ReadDevPropertyList device is null, deviceName:{}", deviceName);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "device is null");
                return ackResponse;
            }

            boolean flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE,  jsonObject.toJSONString(),  token);
            if (!flag){
                log.error("MaListenerCallback ReadDevPropertyList updateDeviceAttributes error, jsonObject:{}", jsonObject);
                newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                newPayload.put("msg", "updateDeviceAttributes error");
                return ackResponse;
            }else {
                log.info("MaListenerCallback ReadDevPropertyList updateDeviceAttributes success, jsonObject:{}", jsonObject);
            }
        } else if(functionCode.equals("ChangeMqttConnectInfo")){

        } else if(functionCode.equals("DeleteDev")){
            log.info("MaListenerCallback DeleteDev start, msg:{}", msg);
            JSONObject payload = jsonObject.getJSONObject("Payload");
            if (payload.isEmpty()){
                log.error("MaListenerCallback DeleteDev Payload is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "Payload is empty");
                return ackResponse;
            }
            JSONArray deviceIds = payload.getJSONArray("DeviceIds");
            if (deviceIds.isEmpty()){
                log.error("MaListenerCallback DeleteDev DeviceIds is empty, msg:{}", msg);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "DeviceIds is empty");
                return ackResponse;
            }
            List<DeviceBasicData> devices = rexolarApiClient.getToRelationsInfo(token, gateway.getCoreId(), "DEVICE");
            if (CollectionUtils.isEmpty( devices)){
                log.error("MaListenerCallback DeleteDev devices is empty, gateway:{}", gateway);
                newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                newPayload.put("msg", "devices is empty");
                return ackResponse;
            }
            List<String> deviceNames = devices.stream().map(DeviceBasicData::getName).collect(Collectors.toList());
            for (int i = 0; i < deviceIds.size(); i++) {
                DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceIds.getString(i), token);
                if (device==null){
                    log.error("MaListenerCallback DeleteDev device is null, deviceName:{}", deviceIds.getString(i));
                    newPayload.put("Code", ResultCode.PARAM_ERROR.getStatus());
                    newPayload.put("msg", "device is null");
                    return ackResponse;
                }
                if (deviceNames.contains(device.getName())){
                    boolean relationFlag =  rexolarApiClient.deleteRelationsInfo(
                            token, gateway.getCoreId(), "DEVICE", "Created", device.getCoreId(), "DEVICE");
                    if (!relationFlag){
                        log.error("MaListenerCallback DeleteDev deleteRelationsInfo error, gateway:{}, device:{}", gateway, device);
                        newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                        newPayload.put("msg", "deleteRelationsInfo error");
                        return ackResponse;
                    }
                }else {
                    log.error("MaListenerCallback DeleteDev device relations is not exist, deviceName:{}, deviceNames:{}",
                            deviceIds.getString(i), deviceNames);
                }
                boolean flag = rexolarApiClient.deleteDevice(device.getCoreId(), token);
                if (!flag){
                    log.error("MaListenerCallback DeleteDev deleteDevice error, device:{}", device);
                    newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                    newPayload.put("msg", "deleteDevice error");
                    return ackResponse;
                }else {
                    log.info("MaListenerCallback DeleteDev deleteDevice success, device:{}", device);
                    flag = rexolarApiClient.updateDeviceAttributes(gateway.getCoreId(), ApiConstant.SHARED_SCOPE,  jsonObject.toJSONString(),  token);
                    if (!flag){
                        log.error("MaListenerCallback deleteDevice updateDeviceAttributes error, jsonObject:{}", jsonObject);
                        newPayload.put("Code", ResultCode.SYSTEM_ERROR.getStatus());
                        newPayload.put("msg", "delete gateway device error");
                        return ackResponse;
                    }else {
                        log.info("MaListenerCallback deleteDevice updateDeviceAttributes success, jsonObject:{}", jsonObject);
                    }
                }
            }
        }else {
            log.error("MaListenerCallback functionCode is not support, functionCode:{}", functionCode);
        }
        return ackResponse;
    }
}